package org.afei.ioc.factory;

import org.afei.ioc.data.DataContext;
import org.afei.ioc.entity.BeanEntity;
import org.afei.ioc.handler.HandlerDecorator;

import java.io.Serializable;

/**
 * 抽象的服务工厂，定义处理服务的算法骨架，具体由其子类实现。
 * 使用模板方法模式定义算法的骨架，具体实现有相应的子类去做。
 *
 * @author afei
 * @date 17-5-25.
 */
public abstract class AbstractBeanFactory implements
        BeanFactory, Serializable {

    //----------组件初始化----------begin-----

    protected DataContext beanDefinitionContext;//服务描述信息的存储区
    protected DataContext beanCacheContext; //服务提供者实例的缓存区
    protected HandlerDecorator handlerDecorator;//转换器（元数据到服务描述信息）

    /**
     * 设置服务描述信息的存储区
     *
     * @param beanDefinitionContextName
     * @param resource
     */
    public abstract void setBeanDefinitionContext(String beanDefinitionContextName, String resource);

    /**
     * 设置转换器（元数据到服务描述信息）
     *
     * @param defaultHandler
     * @param handlerName
     */
    public abstract void setHandler(String defaultHandler, String handlerName);

    /**
     * 模板方法
     * 注册服务组件，初始化服务描述信息
     */
    @Override
    public void registerBeanDefinition(String resource, String cacheContext,
                                       String definitionContext, String defaultHandler,
                                       String customHandler) {

        this.setHandler(defaultHandler, customHandler);
        this.setBeanCacheContext(cacheContext);
        this.setBeanDefinitionContext(definitionContext, resource);
    }

    //获取某个服务提供者的服务描述信息
    public abstract BeanEntity getBeanDefinition(String name);
    //----------组件初始化----------end-----


    //----------服务提供者的生命周期-----begin--------

    //检查该服务提供者的实例是否有缓存
    public abstract boolean containsBeanCache(String name);

    //从缓存中获取服务提供者的实例
    public abstract Object getBeanCache(String name);

    public abstract <T> T getBeanCache(String name, Class<T> clazz);

    /**
     * 创建服务提供者
     *
     * @param beanEntity
     * @return
     */
    public abstract Object creatBean(BeanEntity beanEntity);

    public abstract <T> T creatBean(Class<T> clazz);

    //将服务提供者实例注册到缓存
    public abstract Object regiterBeanCache(String name, Object obj);

    @Override
    //模板方法
    //获取服务提供者实例
    public final Object getBean(String name) {

        //获取某个Bean的定义
        BeanEntity beanEntity = getBeanDefinition(name);

        //判断这个Bean是否已经加载到缓存，如果有，直接返回
        if (containsBeanCache(name)) {
            return getBeanCache(name);
        }

        //创建bean的实例
        Object beanObject = this.creatBean(beanEntity);

        //注册到缓存
        regiterBeanCache(name, beanObject);

        //返回bean的实例
        return beanObject;
    }

    //----------服务提供者的生命周期-----end--------

    @Override
    public <T> T getBean(String name, Class<T> clazz) {
        //判断这个Bean是否已经加载到缓存，如果有，直接返回
        if (containsBeanCache(name)) {
            return getBeanCache(name, clazz);
        }

        //创建bean的实例
        T beanObject = this.creatBean(clazz);

        //注册到缓存
        regiterBeanCache(name, beanObject);

        //返回bean的实例
        return beanObject;
    }

    //获取所有的服务描述信息
    public abstract DataContext getBeanDefinitionContext();

    //获取所有的服务实例缓存信息
    public abstract DataContext getBeanCacheContext();

    /**
     * 设置服务提供者实例的缓存区
     *
     * @param beanCacheContextName
     */
    public abstract void setBeanCacheContext(String beanCacheContextName);

}
